package com.example.kotlin.ui

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
import androidx.core.content.ContextCompat
import com.example.kotlin.R

class BarChartView @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null) :
    View(context, attrs) {
    private var mBarPaint: Paint? = null
    private var mAxisPaint: Paint? = null
    private var mYAxisPaint: Paint = Paint()
    private var mXAxisPaint: Paint = Paint().apply { color = 0xffebebeb.toInt() }
    private lateinit var mDataList: DoubleArray//柱状图数据列表
    private var mHorizontalAxis = arrayOf("超大单", "大单", "中单", "小单")
    private val mBars: MutableList<Bar> = ArrayList()
    private val mYAxisScaleValueListGreaterZero = mutableListOf(500.0, 1000.0)
    private val mYAxisScaleValueListLessZero = mutableListOf(-500.0, -1000.0)
    private var mBarWidth = 0f
    private var mMax: Double = 0.0    //数据集合的最大值
    private var mMin: Double = 0.0    //数据集合的最小值
    private var mGap = 0//坐标文本与柱状条之间间隔的变量
    private var mRadius = 0
    private var mTextRect: Rect? = null
    private var mTemp: RectF? = null
    private var mZeroLineX = 0
    private var mYAxisCount = 2
    private var maxBarHeight = 0

    private var mEnableXAxis = true
    private var mEnableYAxis = false

    //直方图距离x轴左边边距
    private var mLeftMargin = 0

    //x轴左边边距
    private var mXAxisStartMargin = 60

    private var mMaxRadius = 90f

    private var mEnableHorizontalLine = true
    private var mWidth = 0
    private var mHight = 0

    init {
        init() //初始化方法
    }

    private fun init() {
        mAxisPaint = Paint()
        mAxisPaint?.isAntiAlias = true
        mAxisPaint?.textSize = 20f
        mAxisPaint?.textAlign = Paint.Align.CENTER
        mYAxisPaint.isAntiAlias = true
        mYAxisPaint.textSize = 30f
        mBarPaint = Paint()
        mBarPaint?.color = Color.BLUE
        mBarPaint?.isAntiAlias = true
        mTextRect = Rect()
        mTemp = RectF()
        //柱状条宽度 默认8dp
        mBarWidth =
            TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60f, resources.displayMetrics)
        //柱状条与坐标文本之间的间隔大小，默认8dp
        mGap = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f, resources.displayMetrics)
            .toInt()
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        //mBars.clear() //清空柱状条Bar的集合

        //去除padding，计算绘制所有柱状条所占的宽和高
        mWidth = w - paddingLeft - paddingRight
        mHight = h - paddingTop - paddingBottom
        mZeroLineX = (mHight - mGap) / 2


    }

    private fun initBarData(mWidth: Int, mHight: Int) {
        if (mDataList == null || mDataList.isEmpty()) {
            return
        }
        //按照数据集合的大小平分宽度
        var step: Int = (mWidth - mLeftMargin - mXAxisStartMargin) / mDataList.size


        //mBarWidth为柱状条宽度的变量，可以设置，mRadius为柱状条宽度的一半
        mBarWidth = Math.min((step * 0.7).toFloat(), mMaxRadius)
        mRadius = (mBarWidth / 2).toInt()

        //计算第一条柱状条的左边位置
        var barLeft = paddingLeft + step / 2 - mRadius + mLeftMargin + mXAxisStartMargin

        //通过坐标文本画笔计算绘制x轴第一个坐标文本占据的矩形边界，这里主要获取其高度，为计算maxBarHeight提供数据
        mAxisPaint?.getTextBounds(mHorizontalAxis[0], 0, mHorizontalAxis[0].length, mTextRect)

        //计算柱状条高度的最大像素大小，mTextRect.height为底部x轴坐标文本的高度，mGap为坐标文本与柱状条之间间隔大小的变量
        maxBarHeight = mHight - mTextRect!!.height() - mGap

        //计算柱状条最大像素大小与最大数据值的比值 大于0的部分和小于0的部分
        //val max = if (maxValue_1 != -1.0) maxValue_1 else mMax
        val heightRatio = Math.abs((maxBarHeight - mGap) * 0.5 / mMax)

        val heightRatio2 = Math.abs((maxBarHeight - mGap) * 0.5 / mMin)

        //遍历数据集合，初始化所有的柱状条Bar对象
        for (data in mDataList) {
            val bar = Bar() //创建柱状条对象
            bar.value = data //设置原始数据
            if (data > 0) {
                bar.transformedValue = bar.value * heightRatio //计算原始数据对应的像素高度大小
            } else {
                bar.transformedValue = bar.value * heightRatio2 //计算原始数据对应的像素高度大小
            }

            //计算绘制柱状条的四个位置
            bar.left = barLeft
            bar.top = (mZeroLineX - bar.transformedValue).toInt()
            bar.bottom = mZeroLineX
            bar.right = (barLeft + mBarWidth).toInt()


            //初始化绘制柱状条时当前的top值，用作动画
            bar.currentTop = bar.bottom

            //将初始化好的Bar添加到集合中
            mBars.add(bar)
            //更新柱状条左边位置，为初始化下一个Bar对象做准备
            barLeft += step
        }
    }

    /**
     * 绘制柱状图
     */
    override fun onDraw(canvas: Canvas) {

        if (mBars.size == 0) {
            return
        }

//        canvas.drawLine(
//            (paddingLeft + mXAxisStartMargin).toFloat(),
//            mZeroLineX.toFloat(),
//            (width - paddingRight).toFloat(),
//            mZeroLineX.toFloat(),
//            mAxisPaint!!
//        )
        //画Y轴
        if (mEnableYAxis) {
            canvas.drawLine(
                paddingLeft.toFloat(), paddingTop.toFloat(), paddingLeft.toFloat(),
                (mZeroLineX * 2).toFloat(), mAxisPaint!!
            )
        }
        //画Y轴0刻度
        val fm: Paint.FontMetrics = mYAxisPaint.fontMetrics
        val deltaY = (fm.descent - fm.ascent) / 2 - fm.descent
        canvas.drawText(
            "0",
            paddingLeft.toFloat(),
            (mZeroLineX + deltaY).toFloat(),
            mYAxisPaint
        )
        //画x轴
        if (mEnableHorizontalLine) {
            val textWidth = mXAxisPaint.measureText("0")
            canvas.drawLine(
                paddingLeft.toFloat() + textWidth * 4,
                (mZeroLineX).toFloat(),
                (width - paddingRight).toFloat(),
                (mZeroLineX).toFloat(),
                mXAxisPaint
            )
        }
        drawYAxisScaleValue(canvas)
        drawBars(canvas)

    }


    /**
     * 绘制柱状条，没有动画效果的模式
     */
    private fun drawBars(canvas: Canvas) {
        //遍历所有的Bar对象，一个个绘制
        for (i in mBars.indices) {
            val bar = mBars[i]
            //绘制底部x轴坐标文本
            val axis = mHorizontalAxis[i] //获取对应位置的坐标文本
            //计算绘制文本的起始位置坐标(textX，textY)，textX为柱状条的中线位置，由于我们对画笔mAxisPaint设置了
            //Paint.Align.CENTER，所以绘制出来的文本的中线与柱状条的中线是重合的
            val textX = (bar.left + mRadius).toFloat()
            val textY = (height - paddingBottom).toFloat()
            //绘制x轴坐标文本
            if (mEnableXAxis) {
                mAxisPaint?.textSize = 48f
                val fm: Paint.FontMetrics = mAxisPaint!!.fontMetrics
                val deltaY = (fm.descent - fm.ascent) / 2 - fm.descent
                canvas.drawText(axis, textX, textY + deltaY, mAxisPaint!!)
            }
            //柱状图颜色
            if (bar.value > 0) {
                //#F22323
                val color = ContextCompat.getColor(context, R.color.red_f22323)
                mBarPaint?.color = color
            } else {
                //#278D3A
                mBarPaint?.color = Color.parseColor("#278D3A")
            }


            //设置柱状条矩形
            mTemp!![bar.left.toFloat(), bar.top.toFloat(), bar.right.toFloat()] =
                bar.bottom.toFloat()
            //绘制圆角矩形
            //canvas.drawRoundRect(mTemp!!, mRadius.toFloat(), mRadius.toFloat(), mBarPaint!!)
            //绘制直角矩形
            canvas.drawRect(mTemp!!, mBarPaint!!);
        }

    }

    /**
     * 画y轴刻度
     */
    private fun drawYAxisScaleValue(canvas: Canvas) {
        mYAxisPaint.textAlign = Paint.Align.RIGHT
        val fm: Paint.FontMetrics = mYAxisPaint.fontMetrics
        val deltaY = (fm.descent - fm.ascent) / 2 - fm.descent
        val heightUnit = (maxBarHeight / 2) / mYAxisCount
        mYAxisScaleValueListGreaterZero.forEachIndexed { i, value ->
            val deltaHeight = heightUnit + i * heightUnit
            val textWidth = mXAxisPaint.measureText("$value")
            canvas.drawText(
                "${value.toInt()}",
                paddingLeft.toFloat() + textWidth / 2,
                (mZeroLineX - deltaHeight).toFloat() + deltaY * 2,
                mYAxisPaint
            )
            if (mEnableHorizontalLine) {

                canvas.drawLine(
                    paddingLeft.toFloat() + textWidth,
                    (mZeroLineX - deltaHeight + deltaY),
                    (width - paddingRight).toFloat(),
                    (mZeroLineX - deltaHeight + deltaY),
                    mXAxisPaint
                )
            }
        }
        mYAxisScaleValueListLessZero.forEachIndexed { i, value ->
            val fm: Paint.FontMetrics = mYAxisPaint.fontMetrics
            val deltaY = (fm.descent - fm.ascent) / 2 - fm.descent
            val deltaHeight = heightUnit + i * heightUnit
            val textWidth = mXAxisPaint.measureText("$value")
            canvas.drawText(
                "${value.toInt()}",
                paddingLeft.toFloat() + textWidth / 2,
                (mZeroLineX + deltaHeight).toFloat(),
                mYAxisPaint
            )
            if (mEnableHorizontalLine) {
                canvas.drawLine(
                    paddingLeft.toFloat() + textWidth,
                    (mZeroLineX + deltaHeight - deltaY),
                    (width - paddingRight).toFloat(),
                    (mZeroLineX + deltaHeight - deltaY),
                    mXAxisPaint
                )
            }
        }
    }

    /**
     * 设置水平方向x轴坐标值
     * @param horizontalAxis 坐标值数组，如{"1", "2", "3", "4","5", "6", "7", "8", "9", "10", "11", "12"}
     */
    fun setHorizontalAxis(horizontalAxis: Array<String>) {
        mHorizontalAxis = horizontalAxis
    }

    /**
     * 设置柱状图数据
     * @param dataList 数据数组，如{12, 24, 45, 56, 89, 70, 49, 22, 23, 10, 12, 3}
     * @param max 数据数组中的最大值，如89，最大值用来计算绘制时的高度比例
     */
    fun setDataList(dataList: DoubleArray) {
        mDataList = dataList
        mYAxisScaleValueListGreaterZero.clear()
        mYAxisScaleValueListLessZero.clear()
        if (mDataList.isNotEmpty()) {
            mMax = mDataList.maxOrNull() ?: -0.0
            mMin = mDataList.minOrNull() ?: -0.0
            mMax *= 1.1
            mMin *= 1.1
        }
        if (mMax > 0) {
            mYAxisScaleValueListGreaterZero.apply {
                add(mMax / mYAxisCount)
                add(mMax)
            }
            if (mMin < 0) {
                mYAxisScaleValueListLessZero.apply {
                    add(mMin / mYAxisCount)
                    add(mMin)
                }
            }
        } else if (mMax < 0) {
            mYAxisScaleValueListLessZero.apply {
                add(mMin / mYAxisCount)
                add(mMin)
            }
        }
        initBarData(mWidth, mHight)
        invalidate()


    }

    fun setYAxisCount(mYAxisCount: Int) {
        this.mYAxisCount = mYAxisCount
    }

    private inner class Bar {
        //绘制柱状条的四个位置
        var left = 0
        var top = 0
        var right = 0
        var bottom = 0
        var value //柱状条原始数据的大小
                = 0.0
        var transformedValue //柱状条原始数据大小转换成对应的像素大小
                = 0.0
        var currentTop //柱状图动画中用到，表示柱状条动画过程中顶部位置的变量，取值范围为[0,top]
                = 0

//        fun isInside(x: Float, y: Float): Boolean {
//            return x > left && x < right && y > top && y < bottom
//        }
    }


}